import cacheUtil from '@/utils/cache';
import { message } from 'antd';
import _ from 'lodash';
import { parseUrl, stringify } from 'query-string';
import tool from './tool';

class Ajax {
  //请求错误检测，如果有错误则统一进行错误整理
  errorCheck = (res, conf = {}) => {
    if (typeof res == 'string') {
      try {
        let index = res.indexOf('}');
        res = JSON.parse(res.slice(0, index + 1));
      } catch (error) {}
      if ((res || {}).target) {
        res = {
          code: 401,
          success: false,
          data: {
            redirectUrl: res.target,
          },
        };
      }
      this.redirect(res, 0);
      return Promise.reject(res);
    }
    return this.errorHandler(res);
  };
  onStatus(e, info) {
    console.log(e, info);
  }

  //统一处理错误
  errorHandler(res) {
    if (!res) return;
    //401  无权限重定向
    if ((res || {}).target) {
      res = {
        code: 401,
        success: false,
        data: {
          redirectUrl: res.target,
        },
      };
      this.redirect(res, 0);
      return Promise.reject(res);
    }
    if (res.success) {
      return res;
    }
    if (res.code >= 300) {
      //错误状态码处理

      return Promise.reject(res);
    }
  }

  // 请求重定向
  redirect(res, time = 1000) {
    let redirectUrl;
    try {
      redirectUrl = res.data.location || res.data.redirectUrl;
    } catch (e) {}

    if (redirectUrl) {
      let info = parseUrl(redirectUrl);
      info.query.goto = encodeURI(
        window.location.protocol +
          '//' +
          window.location.hostname +
          window.location.pathname +
          window.location.hash,
      );
      redirectUrl = info.url + '?' + stringify(info.query);

      if (time) {
        setTimeout(() => {
          location.href = redirectUrl;
        }, time);
      } else {
        location.href = redirectUrl;
      }
    }
  }

  request = (info = {}) => {
    const { method = 'get', url, data, headers = {}, mode, dataType } = info;
    // let tenantOrg = localStorage.getItem('gra-orgInfo');
    // let tenantOrg = sessionStorage.getItem('gra-orgInfo');

    // tenantOrg !== 'undefined' && tenantOrg
    //   ? Object.assign(headers, DomainSelect.getParams(), {
    //       locale_info: locales[getLocale()] ? getLocale() : defaultLang,
    //       tenantCheckChosenOrgUuid: JSON.parse(tenantOrg)?.orgUuid,
    //     })
    //   : Object.assign(headers, DomainSelect.getParams(), {
    //       locale_info: locales[getLocale()] ? getLocale() : defaultLang,
    //     });

    //请求头携带信息
    Object.assign({ headers });

    if (method == 'get') {
      let _param =
        data && Object.keys(data).length > 0 ? '?' + stringify(data) : '';
      let p = fetch(url + _param, {
        method: 'GET',
        credentials: 'include',
        mode,
        headers: Object.assign(
          {
            'Content-Type': 'application/json',
            'X-Requested-With': 'XMLHttpRequest',
          },
          headers,
        ),
      }).then((data) => {
        if (data.status != 200) {
          return Promise.reject(data);
        }
        return data.text().then((text) => {
          try {
            return JSON.parse(text);
          } catch (e) {
            return text;
          }
        });
      });
      p.catch((e) => {
        this.onStatusError(e, info);
      });
      return p;
    }
    if (['post', 'put', 'delete'].indexOf(method) >= 0) {
      let bodyData;
      let headersInfo = {
        'Content-Type': 'application/json',
        Accept: 'application/json',
      };
      //formData 格式统一处理
      if (dataType == 'formData') {
        bodyData = new FormData();
        for (const [key, value] of Object.entries(data)) {
          if (!_.isUndefined(value)) {
            bodyData.append(key, value);
          }
        }
        headersInfo = {};
      } else {
        bodyData = JSON.stringify(data);
      }
      let p = fetch(url, {
        method: method.toUpperCase(),
        credentials: 'include',
        headers,
        mode,
        body: bodyData,
        headers: Object.assign(headersInfo, headers),
      }).then((data) => {
        if (data.status != 200) {
          return Promise.reject(data);
        }
        return data.text().then((text) => {
          try {
            return JSON.parse(text);
          } catch (e) {
            return text;
          }
        });
      });
      p.catch((e) => {
        this.onStatusError(e, info);
      });
      return p;
    }
  };

  fuzzyCleanCache(url) {
    return cacheUtil.fuzzyClean(url);
  }

  fetch = (url, data = {}, config = {}, method = 'get') => {
    const {
      disableSuccMsg,
      mode,
      checkError = true,
      expire,
      single,
      headers,
      id,
      dataType,
    } = config;
    let p; // 请求对象

    // 缓存判断
    let name = `${url}___${stringify(data || {})}___${id || ''}`;
    if (name && cacheUtil.get(name)) {
      return Promise.resolve(cacheUtil.getValue(name));
    }

    // 防止重复请求
    if (single) {
      p = tool
        .singleReq(name, () =>
          this.request({ method, url, data, headers, mode, dataType }),
        )
        .then((res) => {
          return tool.jsonCopy(res);
        });
    } else {
      p = this.request({ method, url, data, headers, mode, dataType });
    }

    // 错误检测
    if (checkError) {
      p = p.then(this.errorCheck);
    }
    // 成功提示
    if (!disableSuccMsg) {
      p.then((res) => {
        message.success(res.message || 'Operation successfully');
        return res;
      });
    }

    // 缓存更新
    if (expire) {
      p.then((res) => {
        cacheUtil.update(name, res, expire);
      });
    }

    return p;
  };

  // get请求
  get = (url, data, config = {}) =>
    this.fetch(
      url,
      data,
      Object.assign({ disableSuccMsg: true }, config),
      'get',
    );

  // post请求
  post = (url, data, config = {}) =>
    this.fetch(
      url,
      data,
      Object.assign({ disableSuccMsg: true }, config),
      'post',
    );

  // put请求
  put = (url, data, config = {}) =>
    this.fetch(
      url,
      data,
      Object.assign({ disableSuccMsg: true }, config),
      'put',
    );

  // put请求
  delete = (url, data, config = {}) =>
    this.fetch(
      url,
      data,
      Object.assign({ disableSuccMsg: true }, config),
      'delete',
    );

  // get请求,并成功提示
  getSucc = (url, data, config = {}) => {
    config.disableSuccMsg = false;
    return this.fetch(url, data, config, 'get');
  };

  // post请求,并成功提示
  postSucc = (url, data, config = {}) => {
    config.disableSuccMsg = false;
    return this.fetch(url, data, config, 'post');
  };
}

export default new Ajax();
